﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Xeml.Document;
using Xeml.Document.Contracts;
using Xeml.Sampling;
using Mpi.Common.Collections;
using Xeml.Sampling.Contracts;

namespace CompilerControls
{
    public partial class ProviderManager : UserControl
    {

        private KeyKeyValueCollection<string, Guid, AuthenticationRequestEventArgs> keyChain = new KeyKeyValueCollection<string, Guid, AuthenticationRequestEventArgs>();

        DataProviderResource _lastSelectedProvider = null;
        public DataProviderResource SelectedProvider
        {
            get
            {
                return _lastSelectedProvider;
                //listView1.SelectedItems.Count > 0 ? listView1.SelectedItems[0].Tag as DataProviderResource : _lastSelectedProvider; 
            }
        }

        public ProviderManager()
        {
            InitializeComponent();
            //   kryptonHeaderGroup1.ButtonSpecs[0].Click += new EventHandler(ProviderManager_Click);
            Setup(null);
        }

        private IDocument _xemlDoc;
        public void Setup(IDocument xemlDoc)
        {
            if (_xemlDoc != null)
            {
                _xemlDoc.DocumentResources.DataProvider.ItemAdded -= new EventHandler<Mpi.Common.Collections.ItemEventArgs<DataProviderResource>>(SampleProvider_ItemAdded);
                _xemlDoc.DocumentResources.DataProvider.ItemRemoved -= new EventHandler<Mpi.Common.Collections.ItemEventArgs<DataProviderResource>>(DataProvider_ItemRemoved);
            }

            _xemlDoc = xemlDoc;
            if (_xemlDoc != null)
            {
                _xemlDoc.DocumentResources.DataProvider.ItemAdded += new EventHandler<Mpi.Common.Collections.ItemEventArgs<DataProviderResource>>(SampleProvider_ItemAdded);
                _xemlDoc.DocumentResources.DataProvider.ItemRemoved += new EventHandler<Mpi.Common.Collections.ItemEventArgs<DataProviderResource>>(DataProvider_ItemRemoved);

            }
            InitListView();
            SetupControls();
        }

        private void SetupControls()
        {
            //    buttonSpecHeaderGroup1.Enabled = _xemlDoc != null ? ComponentFactory.Krypton.Toolkit.ButtonEnabled.True : ComponentFactory.Krypton.Toolkit.ButtonEnabled.False;
            kryptonHeaderGroup1.Enabled = _xemlDoc != null;
            //   listView1.Enabled = _xemlDoc != null;
        }

        void SampleProvider_ItemAdded(object sender, Mpi.Common.Collections.ItemEventArgs<DataProviderResource> e)
        {
            AddProviderToList(e.Item);
        }

        private void InitListView()
        {
            // listView1.Items.Clear();

            foreach (ProviderCard item in this.flowLayoutPanel.Controls)
            {

                item.Selected -= new EventHandler(pc_Click);
            }

            flowLayoutPanel.Controls.Clear();
            if (_xemlDoc != null)
            {
                foreach (DataProviderResource p in _xemlDoc.DocumentResources.DataProvider)
                {

                    AddProviderToList(p);
                }
            }

            //if (listView1.Items.Count > 0)
            //    listView1.SelectedIndices.Add(0);
        }

        void DataProvider_ItemRemoved(object sender, Mpi.Common.Collections.ItemEventArgs<DataProviderResource> e)
        {
            ProviderCard toRem = null;
            foreach (ProviderCard pc in flowLayoutPanel.Controls)
            {
                if (pc.DataProvider == e.Item)
                {
                    pc.Selected -= new EventHandler(pc_Click);
                    toRem = pc;
                }
            }
            flowLayoutPanel.Controls.Remove(toRem);
            toRem.Dispose();
        }

        private void AddProviderToList(DataProviderResource p)
        {

            ProviderCard pc = new ProviderCard();
            pc.Selected += new EventHandler(pc_Click);
            pc.DataProvider = p;
            flowLayoutPanel.Controls.Add(pc);
            if (flowLayoutPanel.Controls.Count == 1)
                pc.SelectMe();
            if (p.ComponentState == ComponentLoadState.Loaded)
            {
                p.Provider.AuthenticationRequest += new EventHandler<Xeml.Sampling.AuthenticationRequestEventArgs>(Provider_AuthenticationRequest);

            }
        }

        void pc_Click(object sender, EventArgs e)
        {
            if (_lastSelectedProvider != (sender as ProviderCard).DataProvider)
            {
                this._lastSelectedProvider = (sender as ProviderCard).DataProvider;

                if (SelectedProviderChanged != null)
                    SelectedProviderChanged(this, new EventArgs());
                if (_lastSelectedProvider != null)
                {
                    //if (_lastSelectedProvider.ComponentState == ComponentLoadState.Loaded)
                    //    this.propertyGrid1.SelectedObject = _lastSelectedProvider.Provider.ConfigurationObject;
                    //else
                        this.propertyGrid1.SelectedObject = null;
                    this.kryptonHeaderGroupOptions.ValuesPrimary.Description = "for " + _lastSelectedProvider.FriendlyName;

                    foreach (ProviderCard pc in flowLayoutPanel.Controls)
                    {
                        if (pc != sender)
                        {
                            pc.DeSelect();
                        }
                    }
                }
                else
                {
                    this.propertyGrid1.SelectedObject = null;
                    this.kryptonHeaderGroupOptions.ValuesPrimary.Description = "no provider selected";
                }
            }
        }

        void Provider_AuthenticationRequest(object sender, Xeml.Sampling.AuthenticationRequestEventArgs e)
        {

            IDataProvider provider = sender as IDataProvider;

            AuthenticationRequestEventArgs _pendingCredentials = e;

            if (keyChain.Contains(provider.Uri, _xemlDoc.Id) &&
                provider.TestCredentials(keyChain[provider.Uri, _xemlDoc.Id].UserName,
                keyChain[provider.Uri, _xemlDoc.Id].Password
                ) == ConnectResult.Success)
            {
                e.UserName = keyChain[provider.Uri, _xemlDoc.Id].UserName;
                e.Password = keyChain[provider.Uri, _xemlDoc.Id].Password;
                return;
            }

            AuthenticationForm af = new AuthenticationForm();
            ConnectResult cr = ConnectResult.Failed;
            af.Setup(_pendingCredentials, GetFriendlyName(provider));
            do
            {

                af.ShowDialog(this);
                cr = provider.TestCredentials(_pendingCredentials.UserName, _pendingCredentials.Password);
                if (cr == ConnectResult.Success)
                {
                    keyChain.Add(provider.Uri, _xemlDoc.Id, _pendingCredentials);
                }
            } while (!_pendingCredentials.Cancel && cr == ConnectResult.Failed);

        }

        private string GetFriendlyName(IDataProvider provider)
        {
            var provResource = _xemlDoc.DocumentResources.DataProvider.FirstOrDefault(x => Object.ReferenceEquals(x.Provider,provider));
            if (provResource != null)
                return provResource.FriendlyName;
            else
                return "Unknown provider";
        }

        private void buttonSpecHeaderGroup1_Click(object sender, EventArgs e)
        {
            DataProviderResource spr = new DataProviderResource();
            DataProviderWizard dpwiz = new DataProviderWizard();
            dpwiz.ShowDialog(this.ParentForm);
            if (dpwiz.ProviderResource != null)
                _xemlDoc.DocumentResources.DataProvider.Add(dpwiz.ProviderResource);
        }

        private void listView1_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (_lastSelectedProvider != this.SelectedProvider)
            {
                _lastSelectedProvider = this.SelectedProvider;
                if (SelectedProviderChanged != null)
                    SelectedProviderChanged(this, new EventArgs());
            }
        }

        public event EventHandler SelectedProviderChanged;
    }
}
